#include "stdafx.h"
#include "FontManager.h"

namespace Renderer
{
	//--------------------------------------------------------------------
	//--------------------------------------------------------------------
	//--------------------------------------------------------------------

	FontManager::FontManager(D3DRenderer& _rRenderer)
	:	m_rRenderer(_rRenderer),
		m_mFonts(),
		m_mTexts(),
		m_pTextSprite(NULL),
		m_oCurrentColor(0xffffffff),
		m_sLogPixelsY(0)
	{
		if ( FAILED( D3DXCreateSprite( m_rRenderer.GetDevice(), &m_pTextSprite ) ) )
		{
			m_pTextSprite = NULL;
		}

		HDC hDC = GetDC( NULL );
		m_sLogPixelsY = GetDeviceCaps( hDC, LOGPIXELSY );
		ReleaseDC( NULL, hDC );

		D3DXMatrixIdentity( &m_oWorld );
	}

	FontManager::~FontManager()
	{
		if ( NULL != m_pTextSprite )
		{
			m_pTextSprite->Release();
			m_pTextSprite = NULL;
		}
	}

	void FontManager::Render()
	{
		TextInfoMap::iterator iTextInfoPair = m_mTexts.begin();
		TextInfoMap::iterator iTextInfoEnd = m_mTexts.end();

		if ( NULL != m_pTextSprite )
		{
			m_pTextSprite->Begin( D3DXSPRITE_ALPHABLEND | D3DXSPRITE_SORT_TEXTURE );
		}

		while ( iTextInfoEnd != iTextInfoPair )
		{
			ID3DXFont* pFont = iTextInfoPair->first;
			TextInfoVec& vTexts = iTextInfoPair->second;
			TextInfoVec::iterator iText = vTexts.begin();
			TextInfoVec::iterator iTextEnd = vTexts.end();

			while ( iTextEnd != iText )
			{
				TextInfo& rText = *iText;

				pFont->DrawText( m_pTextSprite, rText.m_wstrText.c_str(), -1, &rText.m_oRect, DT_NOCLIP, rText.m_oColor );

				++iText;
			}

			vTexts.clear();
			++iTextInfoPair;
		}

		if ( NULL != m_pTextSprite )
		{
			m_pTextSprite->End();
		}
	}

	const Matrix& FontManager::GetWorldTransform() const
	{
		return m_oWorld;
	}

	bool FontManager::AddFont(const string& _strName, const FontInfo& _rInfo)
	{
		bool bResult = false;

		DataKey Key = 0;
		MakeKey( Key, _strName );

		if ( m_mFonts.end() == m_mFonts.find( Key ) )
		{
			ID3DXFont* pFont = NULL;
			const int sHeight = -(int)_rInfo.m_uHeight * m_sLogPixelsY / 72;
			HRESULT hResult = D3DXCreateFont( m_rRenderer.GetDevice(),
				sHeight,							// Height
				0,									// Width
				_rInfo.m_uWeight,					// Weight
				1,									// MipLevels, 0 = autogen mipmaps
				_rInfo.m_bItalic ? TRUE : FALSE,	// Italic
				DEFAULT_CHARSET,					// CharSet
				OUT_DEFAULT_PRECIS,					// OutputPrecision
				DEFAULT_QUALITY,					// Quality
				DEFAULT_PITCH | FF_DONTCARE,		// PitchAndFamily
				_rInfo.m_wstrFontName.c_str(),		// pFaceName
				&pFont );							// ppFont
			if ( SUCCEEDED( hResult ) )
			{
				m_mFonts[Key] = pFont;
				bResult = true;
			}
		}

		return bResult;
	}

	void FontManager::RemoveFont(const string& _strName)
	{
		DataKey Key = 0;
		MakeKey( Key, _strName );

		FontPtrMap::iterator iFontPair = m_mFonts.find( Key );
		if ( m_mFonts.end() != iFontPair )
		{
			ID3DXFont* pFont = iFontPair->second;
			m_mFonts.erase( iFontPair );
			// also remove texts depending on font
			TextInfoMap::iterator iTextInfoPair = m_mTexts.find( pFont );
			if ( m_mTexts.end() != iTextInfoPair )
			{
				m_mTexts.erase( iTextInfoPair );
			}
			// release font
			pFont->Release();
		}
	}

	void FontManager::SetColor(const D3DCOLOR& _rColor)
	{
		m_oCurrentColor = _rColor;
	}

	void FontManager::Printf(const string& _strName, const unsigned int& _uLeft, const unsigned int& _uTop, const wchar_t* _pwszFormat, ...)
	{
		DataKey Key = 0;
		MakeKey( Key, _strName );

		FontPtrMap::iterator iFontPair = m_mFonts.find( Key );
		if ( m_mFonts.end() != iFontPair )
		{
			va_list oArgs;
			va_start( oArgs, _pwszFormat );
			vswprintf_s( m_wszBuffer, c_TextBufferSize, _pwszFormat, oArgs );
			va_end( oArgs );

			TextInfo oTextInfo;
			m_mTexts[iFontPair->second].push_back( oTextInfo );
			TextInfo& rTextInfo = m_mTexts[iFontPair->second].back();
			rTextInfo.m_oColor = m_oCurrentColor;
			rTextInfo.m_wstrText = m_wszBuffer;
			rTextInfo.m_oRect.left = _uLeft;
			rTextInfo.m_oRect.top = _uTop;
			rTextInfo.m_oRect.right = 0;
			rTextInfo.m_oRect.bottom = 0;
		}
	}
}
